<?php
namespace waf\server;

use \waf\Waf;
use \waf\log\Log;

class BaseServer
{
    protected $objSServer;
    protected $objYaf;
    protected $strMasterFile;
    protected $strServerType;

    public function init()
    {
        Log::logSystem("in", __FILE__, __LINE__, __FUNCTION__);

        if($this->strServerType == 'http')
        {
            $this->objSServer = new \swoole_http_server(Waf::getConfig('server', 'ip'), Waf::getConfig('server', 'port'));
        }else{
            $this->objSServer = new \swoole_server(Waf::getConfig('server', 'ip'), Waf::getConfig('server', 'port'), Waf::getConfig('server', 'mode'), Waf::getConfig('server', 'sock_type'));
        }

        // 设置setting
        $arrSetting = Waf::getConfig('server', 'setting');
        if($arrSetting && is_array($arrSetting))
        {
            // 设置swoole日记文件
            if(!isset($arrSetting['log_file']))
                $arrSetting['log_file'] = Waf::getConfig('log', 'log_path').'/'.Waf::getConfig('log', 'log_file').'.swoole';

            if(!isset($arrSetting['log_level']))
                $arrSetting['log_level'] = Waf::getConfig('log', 'log_level');

            $this->objSServer->set($arrSetting);
        }

        // 设置回调
        $this->objSServer->on('Connect',        [$this, 'onConnect']);
        $this->objSServer->on('Close',          [$this, 'onClose']);
        $this->objSServer->on('Receive',        [$this, 'onReceive']);  // tcp
        $this->objSServer->on('Packet',         [$this, 'onPacket']);   // udp
        $this->objSServer->on('Request',        [$this, 'onRequest']);  // http
        $this->objSServer->on('Start',          [$this, 'onMasterStart']);
        $this->objSServer->on('ManagerStart',   [$this, 'onManagerStart']);
        $this->objSServer->on('ManagerStop',    [$this, 'onManagerStop']);
        $this->objSServer->on('WorkerStart',    [$this, 'onWorkerStart']);
        $this->objSServer->on('ShutDown',       [$this, 'onShutdown']);
        $this->objSServer->on('Timer',          [$this, 'onTimer']);

        // 设置全局可获取对象
        Waf::initObjServer($this);

        // init yaf
        $this->objYaf = new \Yaf_Application(['application' => Waf::getConfig('app')]);

        Log::logSystem("out", __FILE__, __LINE__, __FUNCTION__); 
    }

    //==== swoole 回调开始
    public function onMasterStart($objSServer)
    {
        Log::logSystem("in", __FILE__, __LINE__, __FUNCTION__);
        $name           = Waf::getConfig('server', 'name');
        $intMasterPid   = $objSServer->master_pid;
        $this->_setProcessName(Waf::getConfig('server', 'name').'_master_'.$intMasterPid);
        $this->strMasterFile = Waf::getConfig('log', 'log_path')."/master_".$intMasterPid."_{$name}.pid";
        file_put_contents($this->strMasterFile, PUB_FILE);
        Log::logSystem("out", __FILE__, __LINE__, __FUNCTION__);
    }

    public function onShutdown($objSServer)
    {
        Log::logSystem("in. masterFile=".$this->strMasterFile, __FILE__, __LINE__, __FUNCTION__);
        if(file_exists($this->strMasterFile))
        {
            unlink($this->strMasterFile);
        }
    }

    public function onManagerStart($objSServer)
    {
        Log::logSystem("in", __FILE__, __LINE__, __FUNCTION__);
        $intMasterPid   = $objSServer->master_pid;
        $intManagerPid  = $objSServer->manager_pid;
        $this->_setProcessName(Waf::getConfig('server', 'name').'_manager_'.$intMasterPid);
        Log::logSystem("out", __FILE__, __LINE__, __FUNCTION__);
    }

    public function onManagerStop($objSServer)
    {
        Log::logSystem("in. masterFile=".$this->strMasterFile, __FILE__, __LINE__, __FUNCTION__);
        if(file_exists($this->strMasterFile))
        {
            unlink($this->strMasterFile);
        }
    }

    public function onWorkerStart($objSServer, $workerId)
    {
        $name = Waf::getConfig('server', 'name');
        if ($workerId >= Waf::getConfig('server', 'setting')['worker_num']) {
            $this ->_setProcessName($name.'_task_'.$objSServer->master_pid.'_'.$workerId);
        } else {
            $this ->_setProcessName($name.'_work_'.$objSServer->master_pid.'_'.$workerId);
        }

        Log::logSystem("onWorkerStart", __FILE__, __LINE__, __FUNCTION__);
    }

    public function onConnect($objSServer, $fd)
    {
        Log::logSystem("onConnect", __FILE__, __LINE__, __FUNCTION__);
    }

    public function onClose($objSServer, $fd)
    {
        Log::logSystem("onClose", __FILE__, __LINE__, __FUNCTION__);
    }

    public function onReceive($objSServer, $fd, $from_id, $data)
    {
        Log::logSystem("onReceive", __FILE__, __LINE__, __FUNCTION__);
    }

    public function onPacket($objSServer, $data, $arrAddr)
    {
        Log::logSystem("onReceive", __FILE__, __LINE__, __FUNCTION__);
    }

    public function onRequest($objRequest, $objResponse)
    {
        Log::logSystem("onRequest", __FILE__, __LINE__, __FUNCTION__);
    }

    public function onTimer($objSServer, $interval)
    {
        Log::logSystem("onTimer", __FILE__, __LINE__, __FUNCTION__);
    }
    //==== swoole 回调结束

    public function _setProcessName($name)
    {
        if (function_exists('cli_set_process_title')) {
            cli_set_process_title($name);
        } else if (function_exists('swoole_set_process_name')) {
            swoole_set_process_name($name);
        } else {
            trigger_error(__METHOD__ . " failed. require cli_set_process_title or swoole_set_process_name.");
        }
    }

    public function run()
    {
        Log::logSystem("in", __FILE__, __LINE__, __FUNCTION__);
        $this->objSServer->start();
        Log::logSystem("out", __FILE__, __LINE__, __FUNCTION__);
    }

    public function start()
    {
        Log::logSystem("in", __FILE__, __LINE__, __FUNCTION__);
        $this->init();
        $this->run();
        Log::LogSystem("out", __FILE__, __LINE__, __FUNCTION__);
    }

    public function route($data)
    {
        $strR = '/';
        
        if($data)
        {
            $class  = Waf::getConfig('route', 'class');
            $func   = Waf::getConfig('route', 'function');

            if($class && $func)
            {
                $strR = $class::$func($data);
            }
        }

        return $strR;
    }
}
?>